﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlServerCe;
using System.IO;
using Mimoza.Common;

namespace Mimoza.DBLayer.SQLSC
{
    class SQLCS_DBUpdate : Mimoza.Common.IDBUpdateRepository
    {
        private SqlCeConnection connection = null;

        private SQLCS_DBUpdate()
        { }

        public SQLCS_DBUpdate(SqlCeConnection conn)
        {
            connection = conn;
        }

        #region IDBUpdate Members

        public Mimoza.Common.UpdateRecord GetUpdate(Guid ID)
        {
            SqlCeCommand cmd = null;
            ContainerRecord record = new ContainerRecord();

            try
            {
                cmd = connection.CreateCommand();
                cmd.CommandText = SQLCS_Helper.SelectUpdateString + " WHERE [ID] = @ID";
                cmd.Parameters.AddWithValue("@ID", ID);

                SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable);
                string[] columns = rs.ResultSetView.Columns;

                if (!rs.ReadFirst()) return null;

                return SQLCS_Helper.UpdateRecordFromResultSet(rs, columns);
            }
            finally
            {
                if (null != cmd) cmd.Dispose();
            }
        }

        public IEnumerable<Mimoza.Common.UpdateRecord> GetUpdates()
        {
            SqlCeCommand cmd = null;

            try
            {
                cmd = connection.CreateCommand();
                cmd.CommandText = SQLCS_Helper.SelectUpdateString;

                SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable);
                string[] columns = rs.ResultSetView.Columns;

                if (!rs.ReadFirst()) yield break;

                do
                {
                    yield return SQLCS_Helper.UpdateRecordFromResultSet(rs, columns);
                } while (rs.Read());
            }
            finally
            {
                if (null != cmd) cmd.Dispose();
            }
        }

        public void Insert(Mimoza.Common.UpdateRecord update)
        {
            SqlCeCommand cmd = null;

            try
            {
                if (update.ID == null || update.ID == Guid.Empty)
                {
                    update.ID = Guid.NewGuid();
                }

                SaveUpdateFile(update);

                cmd = connection.CreateCommand();
                
                SQLCS_Helper.GreateInsertCommand(cmd, "Updates", update);

                cmd.ExecuteNonQuery();

                RaiseOnObjectChanged(new DBObjectChangedEventArgs(update, DBEventType.ObjectInserted));
            }
            finally
            {
                if (null != cmd) cmd.Dispose();
            }
        }

        public void Update(Mimoza.Common.UpdateRecord update)
        {
            SqlCeCommand cmd = null;

            try
            {
                SaveUpdateFile(update);

                cmd = connection.CreateCommand();

                SQLCS_Helper.GreateUpdateCommand(cmd, "Updates", update);

                cmd.ExecuteNonQuery();

                RaiseOnObjectChanged(new DBObjectChangedEventArgs(update, DBEventType.ObjectUpdated));
            }
            finally
            {
                if (null != cmd) cmd.Dispose();
            }
        }

        public void Delete(Mimoza.Common.UpdateRecord update)
        {
            SqlCeCommand cmd = null;

            try
            {
                cmd = connection.CreateCommand();
                cmd.CommandText = "DELETE FROM Updates WHERE [ID] = @ID";
                cmd.Parameters.AddWithValue("@ID", update.ID);

                cmd.ExecuteNonQuery();

                RaiseOnObjectChanged(new DBObjectChangedEventArgs(update, DBEventType.ObjectDeleted));
                EraseUpdateFile(update);
            }
            finally
            {
                if (null != cmd) cmd.Dispose();
            }
        }

        public event EventHandler<DBObjectChangedEventArgs> OnObjectChanged;

        private void RaiseOnObjectChanged(DBObjectChangedEventArgs e)
        {
            EventHandler<DBObjectChangedEventArgs> handler = OnObjectChanged;

            if (handler != null)
            {
                handler(this, e);
            }
        }

        #endregion

        private static void SaveUpdateFile(Mimoza.Common.UpdateRecord update)
        {
            if (update.UpdateFileBody != null && update.UpdateFileBody.Length>0)
            {
                string fileName = GenerateUpdateFileName();
                SaveUpdateFileName(fileName, update.UpdateFileBody);
                update.UpdateFileName = fileName;
                update.UpdateFileBody = null;
            }
        }

        private static void EraseUpdateFile(Mimoza.Common.UpdateRecord update)
        {
            if (!string.IsNullOrEmpty(update.UpdateFileName))
            {
                File.Delete(update.UpdateFileName);
            }
        }

        public static void SaveUpdateFileName(string fileName, byte[] body)
        {
            using (FileStream fs = File.Open(fileName, FileMode.CreateNew))
            {
                fs.Write(body, 0, body.Length);
            }
        }

        public static string GenerateUpdateFileName()
        {
            const string UpdateRepositoryFolderName = "UpdateRepository";

            string fileNamePath = Path.Combine(Common.GlobalSettings.DataPath, UpdateRepositoryFolderName);
            
            Directory.CreateDirectory(fileNamePath);

            string fileId = Guid.NewGuid().ToString();

            return Path.Combine(fileNamePath, fileId);
        }
    }
}
